import AttributeUtil from '@/AttributeUtil';
import BaseUtil from '@/BaseUtil';
import SelectUtil from '@/SelectUtil';
import UnitDamagedEvent from '@/event/UnitDamagedEvent';
import UnitDeathEvent from '@/event/UnitDeathEvent';
import { OrderId } from '@/globals/order';

declare global {
    interface AppAttribute extends SolarAttribute {
        // 仇恨增加倍率
        hatredyIncrease?: number;
        // 治疗产生的仇恨减少倍率
        healActionhatredyDecrease?: number;
    }
}

export default class Hatredysystem {
    private emityTable: Map<unit, Map<unit, number>> = new Map();
    private battalStateTimer: Map<unit, number> = new Map();
    private battleCurrentTarget: Map<unit, unit> = new Map();
    constructor() {
        this.init();
        // 受伤时记录仇恨
        se.onUnitDamaged(this.action);
        //死亡时清空仇恨
        se.onUnitDeath(this.deathAction);
        // 定时器记录战斗状态，如果脱离战斗则清空仇恨
        BaseUtil.onTimer(4, this.timerAction);
    }
    timerAction() {
        let map = HatredySystemInstance.battalStateTimer;
        for (let [u, v] of map) {
            v -= 1;
            if (v <= 0) {
                // 敌方处理
                if (IsUnitEnemy(u, Player(0))) {
                    // 清空仇恨表
                    HatredySystemInstance.emityTable.delete(u);
                    // 脱离战斗状态
                    map.delete(u);
                    // 清空仇恨目标
                    HatredySystemInstance.battleCurrentTarget.delete(u);
                    // 发送停止指令
                    IssueImmediateOrderById(u, OrderId.Stop);
                } else {
                    // 玩家单位脱离战斗状态，清空敌方单位的仇恨表
                    // 脱离战斗状态
                    map.delete(u);
                    HatredySystemInstance.clearUnitHatred(u);
                }
            } else {
                map.set(u, v);
            }
            let tar = HatredySystemInstance.getMaxHatredyUnit(u);
            HatredySystemInstance.battleCurrentTarget.set(u, tar);
            IssueTargetOrderById(u, OrderId.Attackonce, tar);
        }
        return true;
    }
    clearUnitHatred(u: unit) {
        let hMap = this.emityTable;
        for (let [k, v] of hMap) {
            if (v.get(u)) {
                v.delete(u);
            }
        }
    }
    getMaxHatredyValue(u: unit): number {
        let map = this.emityTable.get(u);
        if (!map) return 0;
        let max = 0;
        for (let [k, v] of map) {
            if (v > max) {
                max = v;
            }
        }
        return max;
    }
    getMaxHatredyUnit(u: unit): unit | null {
        let map = this.emityTable.get(u);
        if (!map) return null;
        let max = 0;
        let maxUnit: unit | null = null;
        for (let [k, v] of map) {
            if (v > max) {
                max = v;
                maxUnit = k;
            }
        }
        return maxUnit;
    }
    deathAction(this: void, d: UnitDeathEvent) {
        let u = GetTriggerUnit();
        BaseUtil.runLater(1, () => {
            if (HatredySystemInstance.emityTable.has(u)) {
                HatredySystemInstance.emityTable.delete(u);
                // 脱离战斗
                HatredySystemInstance.removeUnitBattalState(u);
            }
        });
    }
    init() {}
    action(this: void, d: UnitDamagedEvent) {
        let u = GetTriggerUnit();
        // 死亡单位不需要记录仇恨
        if (IsUnitDeadBJ(u)) return;
        if (d.damage <= 0) return;
        // source也进入战斗记录
        let ds = d.damageSource;
        HatredySystemInstance.battalStateTimer.set(ds, 3);
        // 非玩家敌人不需要记录仇恨
        if (!IsUnitEnemy(u, Player(0))) return;
        if (!HatredySystemInstance.emityTable.has(u)) {
            HatredySystemInstance.emityTable.set(u, new Map());
        }
        // 计算仇恨值
        HatredySystemInstance.IncreaseHatred(u, ds, d.damage);
    }
    // 增加指定单位的仇恨值
    IncreaseHatred(u: unit, ds: unit, val: number) {
        let map = this.emityTable.get(u);
        let rate = 1 + (AttributeUtil.getUnitAttribute(ds)?.hatredyIncrease ?? 0);
        let v = map.get(ds) ?? 0;
        v += val * rate * 0.01;
        map.set(ds, v);
        this.addUnitBattalState(ds);
    }
    // 治疗产生仇恨
    HealActionIncreaseHatred(ds: unit, val: number) {
        // AI单位忽略
        if (IsUnitEnemy(ds, Player(0))) return;
        let us = SelectUtil.getEnemyUnitsInRange(ds, 1100);
        for (let u of us) {
            let map = this.emityTable.get(u);
            if (map == null) {
                map = new Map<unit, number>();
                this.emityTable.set(u, map);
            }
            let rate = 1 - (AttributeUtil.getUnitAttribute(ds)?.healActionhatredyDecrease ?? 0);
            let v = map.get(ds) ?? 0;
            v += val * rate * 0.01;
            map.set(ds, v);
        }
        this.addUnitBattalState(ds);
    }
    // 范围增加仇恨
    public addHatredyInRange(ds: unit, range: number, val: number) {
        let us = SelectUtil.getEnemyUnitsInRange(ds, range);
        for (let u of us) {
            let map = this.emityTable.get(u);
            let rate = 1 + (AttributeUtil.getUnitAttribute(ds)?.hatredyIncrease ?? 0);
            let v = map.get(ds) ?? 0;
            map.set(ds, v + val * rate * 0.01);
        }
        this.addUnitBattalState(ds);
    }
    // 记录战斗状态
    addUnitBattalState(ds: unit) {
        this.battalStateTimer.set(ds, 3);
    }
    // 脱离战斗
    removeUnitBattalState(ds: unit) {
        this.battalStateTimer.delete(ds);
    }
    // 取目标仇恨列表
    getUnitHatredList(u: unit) {
        return this.emityTable.get(u);
    }
}
